package database

import (
	"context"
	"fmt"
	"sync"
	"time"

	gaussdb "github.com/HuaweiCloudDeveloper/gaussdb-go"
)

// Config 数据库配置
type Config struct {
	Host            string
	Port            uint16
	User            string
	Password        string
	Database        string
	SSLMode         string
	MaxConns        int32
	MinConns        int32
	ConnMaxLifetime time.Duration
	ConnTimeout     time.Duration
}

// GetConnectionURL 根据配置生成 GaussDB 连接URL
func (c *Config) GetConnectionURL() string {
	return fmt.Sprintf("gaussdb://%s:%s@%s:%d/%s?sslmode=%s",
		c.User,
		c.Password,
		c.Host,
		c.Port,
		c.Database,
		c.SSLMode,
	)
}

// DefaultConfig 返回默认配置
func DefaultConfig() *Config {
	return &Config{
		Host:            "localhost",
		Port:            8000,
		User:            "admin",
		Password:        "",
		Database:        "ddl_checker",
		SSLMode:         "require",
		MaxConns:        20,
		MinConns:        2,
		ConnMaxLifetime: 30 * time.Minute,
		ConnTimeout:     5 * time.Second,
	}
}

// GaussDBPool GaussDB 连接池
type GaussDBPool struct {
	config       *Config
	connections  chan *gaussdb.Conn
	activeConns  []*gaussdb.Conn
	mu           sync.RWMutex
	maxConns     int
	minConns     int
	currentConns int
	closed       bool
}

// NewGaussDBPool 创建 GaussDB 连接池
func NewGaussDBPool(ctx context.Context, config *Config) (*GaussDBPool, error) {
	pool := &GaussDBPool{
		config:      config,
		maxConns:    int(config.MaxConns),
		minConns:    int(config.MinConns),
		connections: make(chan *gaussdb.Conn, config.MaxConns),
		activeConns: make([]*gaussdb.Conn, 0, config.MaxConns),
	}

	// 创建最小连接数
	for i := 0; i < pool.minConns; i++ {
		conn, err := pool.createConnection(ctx)
		if err != nil {
			pool.Close()
			return nil, fmt.Errorf("创建初始连接失败: %w", err)
		}
		pool.connections <- conn
		pool.activeConns = append(pool.activeConns, conn)
		pool.currentConns++
	}

	return pool, nil
}

// createConnection 创建新的数据库连接
func (p *GaussDBPool) createConnection(ctx context.Context) (*gaussdb.Conn, error) {
	url := p.config.GetConnectionURL()

	conn, err := gaussdb.Connect(ctx, url)
	if err != nil {
		return nil, fmt.Errorf("连接 GaussDB 失败: %w", err)
	}

	// 验证连接
	var now time.Time
	err = conn.QueryRow(ctx, "SELECT NOW()").Scan(&now)
	if err != nil {
		conn.Close(ctx)
		return nil, fmt.Errorf("验证 GaussDB 连接失败: %w", err)
	}

	return conn, nil
}

// GetConnection 从连接池获取连接
func (p *GaussDBPool) GetConnection(ctx context.Context) (*gaussdb.Conn, error) {
	p.mu.Lock()
	defer p.mu.Unlock()

	if p.closed {
		return nil, fmt.Errorf("连接池已关闭")
	}

	select {
	case conn := <-p.connections:
		return conn, nil
	default:
		// 如果没有可用连接且未达到最大连接数，创建新连接
		if p.currentConns < p.maxConns {
			conn, err := p.createConnection(ctx)
			if err != nil {
				return nil, err
			}
			p.activeConns = append(p.activeConns, conn)
			p.currentConns++
			return conn, nil
		}
		return nil, fmt.Errorf("连接池已满，无可用连接")
	}
}

// PutConnection 将连接归还到连接池
func (p *GaussDBPool) PutConnection(conn *gaussdb.Conn) {
	p.mu.Lock()
	defer p.mu.Unlock()

	if p.closed {
		conn.Close(context.Background())
		return
	}

	select {
	case p.connections <- conn:
		// 连接已归还到池中
	default:
		// 连接池已满，关闭连接
		conn.Close(context.Background())
		// 从活动连接列表中移除
		for i, activeConn := range p.activeConns {
			if activeConn == conn {
				p.activeConns = append(p.activeConns[:i], p.activeConns[i+1:]...)
				p.currentConns--
				break
			}
		}
	}
}

// Close 关闭连接池
func (p *GaussDBPool) Close() {
	p.mu.Lock()
	defer p.mu.Unlock()

	if p.closed {
		return
	}
	p.closed = true

	// 关闭所有活动连接
	for _, conn := range p.activeConns {
		conn.Close(context.Background())
	}

	// 关闭通道中的连接
	close(p.connections)
	for conn := range p.connections {
		conn.Close(context.Background())
	}
}

// Stats 获取连接池统计信息
func (p *GaussDBPool) Stats() map[string]interface{} {
	p.mu.RLock()
	defer p.mu.RUnlock()

	return map[string]interface{}{
		"status":       "正常",
		"total_conns":  p.currentConns,
		"idle_conns":   len(p.connections),
		"active_conns": p.currentConns - len(p.connections),
		"max_conns":    p.maxConns,
		"min_conns":    p.minConns,
	}
}

// DB 数据库连接管理器
type DB struct {
	gaussPool *GaussDBPool
	config    *Config
}

// NewDB 创建新的数据库管理器实例
func NewDB(config *Config) *DB {
	if config == nil {
		config = DefaultConfig()
	}
	return &DB{
		config: config,
	}
}

// InitPool 初始化连接池
func (db *DB) InitPool(ctx context.Context) error {
	pool, err := NewGaussDBPool(ctx, db.config)
	if err != nil {
		return fmt.Errorf("初始化 GaussDB 连接池失败: %w", err)
	}
	db.gaussPool = pool
	return nil
}

// GetGaussPool 获取 GaussDB 连接池
func (db *DB) GetGaussPool() *GaussDBPool {
	return db.gaussPool
}

// GetConnection 获取原生 GaussDB 连接
func (db *DB) GetConnection(ctx context.Context) (*gaussdb.Conn, error) {
	if db.gaussPool == nil {
		return nil, fmt.Errorf("GaussDB 连接池未初始化")
	}
	return db.gaussPool.GetConnection(ctx)
}

// Close 关闭连接池
func (db *DB) Close() {
	if db.gaussPool != nil {
		db.gaussPool.Close()
	}
}

// WithConnection 使用连接池中的连接执行操作
func (db *DB) WithConnection(ctx context.Context, fn func(*gaussdb.Conn) error) error {
	if db.gaussPool == nil {
		return fmt.Errorf("GaussDB 连接池未初始化")
	}

	conn, err := db.gaussPool.GetConnection(ctx)
	if err != nil {
		return fmt.Errorf("获取数据库连接失败: %w", err)
	}
	defer db.gaussPool.PutConnection(conn)

	return fn(conn)
}

// Query 执行查询
func (db *DB) Query(ctx context.Context, sql string, args ...interface{}) (gaussdb.Rows, error) {
	var rows gaussdb.Rows
	err := db.WithConnection(ctx, func(conn *gaussdb.Conn) error {
		r, err := conn.Query(ctx, sql, args...)
		if err != nil {
			return err
		}
		rows = r
		return nil
	})
	return rows, err
}

// Exec 执行命令（INSERT, UPDATE, DELETE等）
func (db *DB) Exec(ctx context.Context, sql string, args ...interface{}) (int64, error) {
	var result int64
	err := db.WithConnection(ctx, func(conn *gaussdb.Conn) error {
		res, err := conn.Exec(ctx, sql, args...)
		if err != nil {
			return err
		}
		result = res.RowsAffected()
		return nil
	})
	return result, err
}

// QueryRow 执行单行查询
func (db *DB) QueryRow(ctx context.Context, sql string, args ...interface{}) gaussdb.Row {
	var row gaussdb.Row
	err := db.WithConnection(ctx, func(conn *gaussdb.Conn) error {
		row = conn.QueryRow(ctx, sql, args...)
		return nil
	})
	if err != nil {
		return nil
	}
	return row
}

// Transaction 执行事务
func (db *DB) Transaction(ctx context.Context, fn func(gaussdb.Tx) error) error {
	if db.gaussPool == nil {
		return fmt.Errorf("GaussDB 连接池未初始化")
	}

	conn, err := db.gaussPool.GetConnection(ctx)
	if err != nil {
		return fmt.Errorf("获取数据库连接失败: %w", err)
	}
	defer db.gaussPool.PutConnection(conn)

	// 开始事务
	tx, err := conn.Begin(ctx)
	if err != nil {
		return fmt.Errorf("开始事务失败: %w", err)
	}

	defer func() {
		if p := recover(); p != nil {
			_ = tx.Rollback(ctx)
			panic(p)
		}
	}()

	if err := fn(tx); err != nil {
		if rbErr := tx.Rollback(ctx); rbErr != nil {
			return fmt.Errorf("事务回滚失败: %v, 原始错误: %w", rbErr, err)
		}
		return err
	}

	if err := tx.Commit(ctx); err != nil {
		return fmt.Errorf("事务提交失败: %w", err)
	}

	return nil
}

// Stats 获取连接池统计信息
func (db *DB) Stats() map[string]interface{} {
	if db.gaussPool == nil {
		return map[string]interface{}{
			"status": "GaussDB 连接池未初始化",
			"type":   "gaussdb",
		}
	}
	stats := db.gaussPool.Stats()
	stats["type"] = "gaussdb"
	return stats
}
